from expression import *
from endvals import *
import sys
sys.path.append(sys.path[0] + "/../LLVM")
from llvmhelper import llvmHelper
from llvm import *
from commonRoutines import commonRoutines

class ifthen(expression):
	def __init__(self,test,then,els = "nil"):
		self.test = test
		self.then = then
		self.els = els
	def evaluate(self,env):
		test = self.test.evaluate(env)
		if(type(test) != type(1==1)):
			print "Error: Test in 'ifthen' should evaulate to a boolean"
		elif(test):
			return self.then.evaluate(env)
		else:
			#print "self.els = ", self.els
			if(self.els != "nil"):
				return self.els.evaluate(env)
				
	def __str__(self):
		return "ifthen( " + str(self.test) + ")\n {" + str(self.then) + "} \n else {" + str(self.els) + "}\n"

	def traverse(self, helper):
		self.test.traverse(helper)
		self.then.traverse(helper)
		if(self.els != "nil"):
			self.els.traverse(helper)
		
	def toLLVM(self, helper):
		helper.descend("ifthen")
		self.test.toLLVM(helper)
		argValues = helper.getReturns()
		

		c = commonRoutines(helper)
		
		numBoolean = helper.getNextLabel()
		errorLabel = helper.getNextLabel()
		iflabel = helper.getNextLabel()
		elselabel = helper.getNextLabel()
		ifEndLabel= helper.getNextLabel()
		elseEndLabel= helper.getNextLabel()
		endlabel = helper.getNextLabel()
		
		#Registers
#		maskReg1 = helper.getNextReg()
#		branchReg1 = helper.getNextReg()		
		
		testRegister = helper.getNextReg()
	
		returnReg = helper.getNextReg()
		
		c.checkType(argValues[0], "bool", numBoolean, errorLabel)
		
		helper.addLLVMLabel(errorLabel)
		c.signalError(20)
		
		helper.addLLVMLabel(numBoolean) 
		
#		helper.addLLVMLine(testRegister + " = icmp eq i32 " + argValues[0] + ", 7")
		helper.addLLVMInst(llvm_icmp_eq(testRegister, argValues[0], "7"))
#		helper.addLLVMLine( "br  i1 " + testRegister + ", label %" + iflabel + ", label %" + elselabel)
		helper.addLLVMInst(llvm_brc(testRegister, iflabel, elselabel))
		
		helper.addLLVMLabel(iflabel)
		self.then.toLLVM(helper)
#		helper.addLLVMLine("br label %" + endlabel)
		helper.addLLVMInst(llvm_br(ifEndLabel))
		
		helper.addLLVMLabel(ifEndLabel, "End of IF label")
		helper.addLLVMInst(llvm_br(endlabel))
		
		helper.addLLVMLabel(elselabel)
		self.els.toLLVM(helper)
#		helper.addLLVMLine("br label %" + endlabel)
		helper.addLLVMInst(llvm_br(elseEndLabel))
		
		helper.addLLVMLabel(elseEndLabel, "End of Else label")
		helper.addLLVMInst(llvm_br(endlabel))
		
		argValues = helper.getReturns()
		labels = helper.getLabels()
		
		helper.addLLVMLabel(endlabel)
		# Made a change here to get it to work                                   \/ this used to be labels[1]
		helper.addLLVMLine(returnReg  + " = phi i32 [ " + str(argValues[1]) + ", %" +  ifEndLabel + " ], [ " + str(argValues[2]) + ", %"+ elseEndLabel + " ]")									
		
		helper.setLabel(endlabel)
		helper.ascend(returnReg)
		
class whileloop(expression):
	def __init__(self,test,body):
		self.test = test
		self.body = body
	def evaluate(self,env):
		test = self.test.evaluate(env)
		if(type(test) != type(1==1)):
			print "Error: Test in 'whileloop' should evaulate to a boolean"
		elif(test == False):
			return void()
		else:
			self.body.evaluate(env)
			self.evaluate(env)
			
	def __str__(self):
		return "whileloop( " + str(self.test) + ")\n {" + str(self.body) + "} \n" 
		
	def traverse(self, helper):
		self.test.traverse(helper)
		self.body.traverse(helper)

	def toLLVM(self, helper):
		helper.descend("whileloop")
		
		compareBlockLabel = helper.getNextLabel()
		loopBlockLabel = helper.getNextLabel()
		endBlockLabel = helper.getNextLabel()
		errorLabel = helper.getNextLabel()
		
		testRegister = helper.getNextReg()
		testRegister2 = helper.getNextReg()
		c = commonRoutines(helper)
		
		
		self.test.toLLVM(helper)
		argValues = helper.getReturns()
		
		c.checkType(argValues[0], "bool", compareBlockLabel, errorLabel)
		
		helper.addLLVMLabel(errorLabel)
		c.signalError(20)
		
		helper.addLLVMLabel(compareBlockLabel, "The comparison!") 
		
		helper.addLLVMInst(llvm_icmp_eq(testRegister, argValues[0], "7"), "Compare boolean to true")
		helper.addLLVMInst(llvm_brc(testRegister, loopBlockLabel, endBlockLabel), "Branch if true!")
		helper.addLLVMLabel(loopBlockLabel, "The loop!")
		self.body.toLLVM(helper)
		self.test.toLLVM(helper)
		secondArgVals = helper.getReturns()
		helper.addLLVMInst(llvm_icmp_eq(testRegister2, secondArgVals[2], "7"), "Compare boolean to true")
		helper.addLLVMInst(llvm_brc(testRegister2, loopBlockLabel, endBlockLabel), "Branch if true!")
		
		helper.addLLVMLabel(endBlockLabel, "End of function!") 
		
		
		helper.setLabel(endBlockLabel)
		helper.ascend(argValues[0])
		
		
		
		
	
